#include "common.h"
#include <linux/socket.h>
#include <linux/net.h>

#define PRINT_LEVEL KERN_INFO
extern int tpl_debug;
extern int tcp_v4_rcv(struct sk_buff *skb);
extern struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb);
extern int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb);

static int my_tcp_do_rcv(struct sock *sk, struct sk_buff *skb)
{
    int ret;
/*
    struct sock *nsk = tcp_v4_hnd_req(sk, skb);
    
    printk(PRINT_LEVEL "[%s] : sk_state = %d, sk = %p, nsk = %p", __FUNCTION__, sk->sk_state, sk, nsk);
*/
    printk("[%s]\n", __FUNCTION__);
    
    memcpy(target_func, saved_st, 4 * NUM_NEED);
    clean_cache(target_func, target_func + NUM_NEED);
    clean_cache(target_func + NUM_NEED * 2, target_func + NUM_NEED * 3);    

    ret = tcp_v4_do_rcv(sk, skb);
	hijack_func();
    return (ret);
}

void jmpfunc(void)
{
    __asm__ __volatile__ ("mov %%pc, %0"
        ::"r"((void *)my_tcp_do_rcv));
}


int my_tcp_rcv_init(void)
{
    printk(PRINT_LEVEL  "%s init, tpl_debug = %d\n", __FUNCTION__, tpl_debug);
    tpl_debug = 1;
    target_func = tcp_v4_do_rcv;
    save_old(target_func);
	hijack_func();
    return 0;
}

void my_tcp_rcv_exit(void)
{

    memcpy((void *)target_func, saved_st, 4 * NUM_NEED);
    clean_cache((void *)target_func, (void *)target_func + NUM_NEED);    
	printk(PRINT_LEVEL  "%s exit, tpl_debug = %d\n", __FUNCTION__, tpl_debug);
    tpl_debug = 0;
}

module_init(my_tcp_rcv_init);
module_exit(my_tcp_rcv_exit);


MODULE_LICENSE("GPL");
MODULE_AUTHOR("tpl.a1406@gmail.com");


